﻿// LogViewControl.cpp
#include "logger/LogListControl.h"

#if defined(_WIN32)

// All heavy includes are now ONLY in the .cpp file
#include <CommCtrl.h>
#include <Richedit.h>
#include <tchar.h>
#include <uxtheme.h>
#include <vssym32.h>

#include <algorithm>
#include <map>
#include <queue>

#include "logger/LogBroker.h"
#include "logger/LogMessageInfo.h"
#include "logger/PatternFormatter.h"
#include "logger/WindowSink.h"
#include "src/LogViewController.h"

#pragma comment(lib, "uxtheme.lib")

namespace Logging {
// --- Control IDs can remain as an internal detail ---
enum class ControlId : int {
  ListView = 2000,
  CheckTrace,
  CheckDebug,
  CheckInfo,
  CheckWarn,
  CheckError,
  CheckCritical,
  StaticSearch,
  EditSearch,
  CheckRegex,
  ButtonClear,
  StatusBar,
  CheckAutoScroll
};

// --- 列定义 ---
enum class Column : int { Icon, Timestamp, Level, ThreadID, Message, COUNT };

// --- 排序状态 ---
struct SortState {
  Column column = Column::Timestamp;
  bool ascending = true;
};

struct ThemeColors {
  COLORREF listBg;
  COLORREF listTextDefault;
  std::map<LogLevel, COLORREF> logLevelColors;

  COLORREF controlBg;
  COLORREF controlText;
  HBRUSH hControlBgBrush;
};

// --- Public constants definition ---
const wchar_t* WC_LOGLIST = L"SuperLogger.LogListControl";

// ========================================================================
// The Hidden Implementation Class Definition
// ========================================================================
class CLogListControl::Impl {
 public:
  Impl();
  ~Impl();

  void SetLogCategory(const std::string& category);

  // Message handlers (these were the private methods of the old class)
  LRESULT OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);
  LRESULT OnDestroy();
  LRESULT OnSize(int width, int height);
  LRESULT OnCommand(int wmId, int wmEvent);
  LRESULT OnLogReady();
  LRESULT OnClear();
  LRESULT OnCtlColor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  LRESULT OnNotify(LPARAM lParam);

  void RefreshDisplay();

  void SetTheme(Theme theme);
  void ApplyCurrentTheme();

  COLORREF GetColorForLogLevel(LogLevel level);
  static void InitializeThemes();

 private:
  friend class CLogListControl;
  void SortDisplayedLogs();
  FilterState GatherFilterStateFromUI() const;

  // ListView 辅助函数
  void CreateListView(HINSTANCE hInstance);
  void SetupListViewColumns();
  void CreateImageList();
  int GetIconIndexForLevel(LogLevel level) const;

  // WM_NOTIFY 的具体处理器
  LRESULT OnListViewGetDispInfo(NMLVDISPINFO* pDispInfo);
  LRESULT OnListViewColumnClick(NMLISTVIEW* pnmv);
  LRESULT OnListViewCustomDraw(NMLVCUSTOMDRAW* pcd);

  // Helper functions
  void CreateChildControls(HINSTANCE hInstance);
  void LayoutChildControls(int width, int height);
  void UpdateStatusBarLayout(int width, int height, int topOffset);
  void UpdateStatusBarText();
  void OnAutoScrollClicked();

  void SetChildControlsFont();

  // All the state is now stored here, hidden from the public header.
  HWND m_hWnd = nullptr;
  HWND m_hListView = nullptr;
  HIMAGELIST m_hImageList = nullptr;

  LogViewController m_controller;
  std::vector<LogMessageInfo>
      m_displayedLogs;    // ★ 新增: 当前显示的数据 (虚拟列表视图的"数据源")
  SortState m_sortState;  // ★ 新增: 排序状态

  // --- 其他成员变量与 CLogViewControl 保持一致 ---
  HFONT m_hFontUI = nullptr;
  std::vector<HWND> m_logLevelCheckBoxes;
  HWND m_hStatusBarWnd = nullptr;
  HWND m_hStatusTotal = nullptr, m_hStatusDisplayed = nullptr,
       m_hStatusError = nullptr, m_hStatusWarn = nullptr;
  HWND m_hChkAutoScroll = nullptr;
  size_t m_nTotalLogs = 0;
  size_t m_nDisplayedLogs = 0;
  std::map<LogLevel, size_t> m_logLevelCounts;
  bool m_bAutoScroll = true;
  std::shared_ptr<WindowSink> m_sink;
  std::string m_category;
  Theme m_currentTheme = Theme::Light;
  static std::map<Theme, ThemeColors> s_themes;
  static bool s_themesInitialized;

  PatternFormatter m_timestampFormatter{"%Y-%m-%d %H:%M:%S.%e"};
  PatternFormatter m_levelFormatter{"%l"};
};

const wchar_t* GetLogListClass() { return WC_LOGLIST; }
void RegisterLogListControl(HINSTANCE hInstance) {
  WNDCLASS wc = {};
  wc.lpfnWndProc = CLogListControl::s_WindowProc;
  wc.hInstance = hInstance;
  wc.lpszClassName = WC_LOGLIST;
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  RegisterClass(&wc);
}
std::map<CLogListControl::Theme, ThemeColors> CLogListControl::Impl::s_themes;
bool CLogListControl::Impl::s_themesInitialized = false;

// ========================================================================
// Public CLogListControl methods (forwarding calls to the Impl)
// ========================================================================

CLogListControl::CLogListControl() : m_pImpl(std::make_unique<Impl>()) {
  // The hWnd parameter is not used here, as the actual handle will be
  // set during the WM_CREATE process. The pointer is passed via lParam.
}

// **CRUCIAL**: The definition of the destructor.
// This empty definition allows the compiler to correctly destroy m_pImpl.
CLogListControl::~CLogListControl() = default;

// Move operations
CLogListControl::CLogListControl(CLogListControl&&) noexcept = default;
CLogListControl& CLogListControl::operator=(CLogListControl&&) noexcept =
    default;

void CLogListControl::SetLogCategory(const std::string& category) {
  if (m_pImpl) {
    m_pImpl->SetLogCategory(category);
  }
}

void CLogListControl::SetPattern(const std::string& pattern) {
  if (m_pImpl) {
    m_pImpl->m_controller.SetPattern(pattern);
  }
}

HWND CLogListControl::GetHwnd() const {
  // 检查 m_pImpl 是否有效，并返回其内部的 HWND
  if (m_pImpl) {
    return m_pImpl->m_hWnd;
  }
  return nullptr;
}

void CLogListControl::SetTheme(Theme theme) {
  if (m_pImpl) {
    m_pImpl->SetTheme(theme);
  }
}

// ========================================================================
// Static Window Procedure (The Bridge)
// ========================================================================
LRESULT CALLBACK CLogListControl::s_WindowProc(HWND hWnd, UINT uMsg,
                                               WPARAM wParam, LPARAM lParam) {
  CLogListControl* pThis = nullptr;
  if (uMsg == WM_NCCREATE) {
    CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
    pThis = reinterpret_cast<CLogListControl*>(pCreate->lpCreateParams);
    SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pThis));
  } else {
    pThis = reinterpret_cast<CLogListControl*>(
        GetWindowLongPtr(hWnd, GWLP_USERDATA));
  }

  if (pThis && pThis->m_pImpl) {
    switch (uMsg) {
      case WM_CREATE:
        return pThis->m_pImpl->OnCreate(
            hWnd, reinterpret_cast<LPCREATESTRUCT>(lParam));
      case WM_SIZE:
        return pThis->m_pImpl->OnSize(LOWORD(lParam), HIWORD(lParam));
      case WM_COMMAND:
        return pThis->m_pImpl->OnCommand(LOWORD(wParam), HIWORD(wParam));
      case WM_DESTROY:
        return pThis->m_pImpl->OnDestroy();
      case WM_SINK_LOG_READY:
        return pThis->m_pImpl->OnLogReady();
      case WM_NOTIFY:  // ★ 新增: 路由 WM_NOTIFY 消息
        return pThis->m_pImpl->OnNotify(lParam);
      case WM_NCDESTROY: {
        SetWindowLongPtr(hWnd, GWLP_USERDATA, 0);
        delete pThis;
        return 0;
      }
      case WM_CTLCOLORSTATIC:
      //{
      //  const auto& colors =
      //  pThis->m_pImpl->s_themes.at(pThis->m_pImpl->m_currentTheme); HDC
      //  hdcStatic = (HDC)wParam; SetTextColor(hdcStatic, colors.controlText);
      //  SetBkColor(hdcStatic, colors.controlBg);
      //  return (LRESULT)colors.hControlBgBrush;
      //}
      case WM_CTLCOLORBTN:
        return pThis->m_pImpl->OnCtlColor(hWnd, uMsg, wParam, lParam);
    }
  }
  return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

// ========================================================================
// Implementation of CLogListControl::Impl methods
// ========================================================================
CLogListControl::Impl::Impl() { InitializeThemes(); }

CLogListControl::Impl::~Impl() {
  if (s_themesInitialized) {
    for (auto& pair : s_themes) {
      DeleteObject(pair.second.hControlBgBrush);
    }
    s_themes.clear();
    s_themesInitialized = false;
  }
}

void CLogListControl::Impl::SetLogCategory(const std::string& category) {
  if (m_category == category) {
    return;  // 类别未改变，无需操作
  }

  auto& broker = LogBroker::GetInstance();

  // 1. 如果已经有一个 Sink，先从旧的类别注销
  if (m_sink) {
    broker.UnregisterSink(m_sink, m_category);
  }

  // 2. 更新类别
  m_category = category;

  // 3. 用新的类别重新注册 Sink
  if (m_sink) {
    broker.RegisterSink(m_sink, m_category);
  }

  // 4. 清空当前视图并刷新，以显示新类别的内容
  m_controller.Clear();
  RefreshDisplay();
}

LRESULT CLogListControl::Impl::OnCreate(HWND hWnd,
                                        LPCREATESTRUCT lpCreateStruct) {
  m_hWnd = hWnd;
  HINSTANCE hInstance = lpCreateStruct->hInstance;

  CreateChildControls(hInstance);  // 创建过滤UI和状态栏
  CreateListView(hInstance);       // 创建核心的ListView控件
  SetChildControlsFont();

  // 初始化 Sink 和 Broker (与之前相同)
  m_sink =
      std::make_shared<WindowSink>(static_cast<NativeWindowHandle>(m_hWnd));
  m_category = "*";
  LogBroker::GetInstance().RegisterSink(m_sink, m_category);

  RECT rcClient;
  GetClientRect(m_hWnd, &rcClient);
  OnSize(rcClient.right, rcClient.bottom);

  RefreshDisplay();
  return 0;
}

LRESULT CLogListControl::Impl::OnDestroy() {
  if (m_hFontUI) {
    DeleteObject(m_hFontUI);
    m_hFontUI = nullptr;
  }

  if (m_hImageList) {
    ImageList_Destroy(m_hImageList);  // ★ 销毁图标列表
  }

  // 确保在窗口销毁时，从 LogBroker 中移除我们的 Sink，防止野指针调用
  if (m_sink) {
    LogBroker::GetInstance().UnregisterSink(m_sink, m_category);
    m_sink.reset();
  }

  return 0;
}

LRESULT CLogListControl::Impl::OnCommand(int wmId, int wmEvent) {
  ControlId id = static_cast<ControlId>(wmId);
  bool needs_refresh = false;

  switch (id) {
    case ControlId::ButtonClear:
      if (wmEvent == BN_CLICKED) {
        m_controller.Clear();
        m_nTotalLogs = 0;
        m_nDisplayedLogs = 0;
        m_logLevelCounts.clear();
        needs_refresh = true;
      }
      break;
    case ControlId::CheckTrace:
    case ControlId::CheckDebug:
    case ControlId::CheckInfo:
    case ControlId::CheckWarn:
    case ControlId::CheckError:
    case ControlId::CheckCritical:
    case ControlId::CheckRegex:
      if (wmEvent == BN_CLICKED) needs_refresh = true;
      break;
    case ControlId::EditSearch:
      if (wmEvent == EN_CHANGE) needs_refresh = true;
      break;
    case ControlId::CheckAutoScroll:
      if (wmEvent == BN_CLICKED) {
        OnAutoScrollClicked();  // 不需要刷新，只处理滚动状态
      }
      break;
  }

  if (wmEvent == BN_CLICKED || wmEvent == EN_CHANGE) {
    if (id >= ControlId::CheckTrace && id <= ControlId::CheckRegex) {
      needs_refresh = true;
    }
  }

  if (needs_refresh) {
    RefreshDisplay();
  }

  return 0;
}

LRESULT CLogListControl::Impl::OnLogReady() {
  std::queue<LogMessageInfo> logs_to_process;

  if (m_sink) {
    m_sink->DrainTo(logs_to_process);
  }

  if (logs_to_process.empty()) {
    return 0;
  }

  bool needs_refresh = false;
  while (!logs_to_process.empty()) {
    const auto& log = logs_to_process.front();
    m_nTotalLogs++;
    m_logLevelCounts[log.level]++;
    m_controller.AddLog(std::move(logs_to_process.front()));
    logs_to_process.pop();
    needs_refresh = true;
  }

  if (needs_refresh) RefreshDisplay();
  return 0;

  return 0;
}

LRESULT CLogListControl::Impl::OnNotify(LPARAM lParam) {
  LPNMHDR pnmh = (LPNMHDR)lParam;

  // 确保通知来自我们的ListView
  if (pnmh->hwndFrom == m_hListView) {
    switch (pnmh->code) {
      // 1. 虚拟列表视图的核心：当需要显示数据时，系统会发送此消息
      case LVN_GETDISPINFO:
        return OnListViewGetDispInfo((NMLVDISPINFO*)lParam);

      // 2. 当用户点击列标题时，系统发送此消息
      case LVN_COLUMNCLICK:
        return OnListViewColumnClick((NMLISTVIEW*)lParam);

      // 3. (高级) 自定义绘制，用于设置行颜色
      case NM_CUSTOMDRAW:
        return OnListViewCustomDraw((NMLVCUSTOMDRAW*)lParam);
    }
  }
  return 0;
}

LRESULT CLogListControl::Impl::OnClear() {
  m_controller.Clear();
  return 0;
}

LRESULT CLogListControl::Impl::OnSize(int width, int height) {
  LayoutChildControls(width, height);
  return 0;
}

void CLogListControl::Impl::RefreshDisplay() {
  // 1. 从UI收集过滤条件
  FilterState filters = GatherFilterStateFromUI();

  // 2. 从控制器获取过滤后的日志，并存入 m_displayedLogs
  m_displayedLogs = m_controller.GetFilteredLogs(filters);

  // 3. 对当前显示的日志进行排序
  SortDisplayedLogs();

  // 4. ★ 通知ListView总共有多少项需要显示
  // 这是虚拟模式的关键。我们不添加项，只告诉它总数。
  ListView_SetItemCountEx(m_hListView, m_displayedLogs.size(),
                          LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL);

  // 5. 如果启用了自动滚动，滚动到新添加的项
  if (m_bAutoScroll) {
    ListView_EnsureVisible(m_hListView, m_displayedLogs.size() - 1, FALSE);
  }

  // 6. 强制重绘以显示新数据
  InvalidateRect(m_hListView, NULL, TRUE);
  UpdateWindow(m_hListView);

  // 7. 更新状态栏
  UpdateStatusBarText();
}

void CLogListControl::Impl::SortDisplayedLogs() {
  if (m_displayedLogs.empty()) return;

  // 使用 std::sort 和一个 lambda 表达式进行排序
  std::sort(m_displayedLogs.begin(), m_displayedLogs.end(),
            [&](const LogMessageInfo& a, const LogMessageInfo& b) {
              int result = 0;
              switch (m_sortState.column) {
                case Column::Timestamp:
                  if (a.timestamp < b.timestamp) result = -1;
                  if (a.timestamp > b.timestamp) result = 1;
                  break;
                case Column::Level:
                  result =
                      static_cast<int>(a.level) - static_cast<int>(b.level);
                  break;
                case Column::ThreadID: {
                  long a_thread_id = 0;
                  long b_thread_id = 0;
                  {
                    std::stringstream ss;
                    ss << a.thread_id;
                    a_thread_id = std::stol(ss.str());
                  }                {
                    std::stringstream ss;
                    ss << a.thread_id;
                    b_thread_id = std::stol(ss.str());
                  }
                  result = a_thread_id - b_thread_id;
                } break;
                case Column::Message:
                  result = a.message.compare(b.message);
                  break;
                default:
                  break;
              }
              return m_sortState.ascending ? (result < 0) : (result > 0);
            });
}

LRESULT CLogListControl::Impl::OnListViewGetDispInfo(NMLVDISPINFO* pDispInfo) {
  LVITEM& item = pDispInfo->item;
  size_t index = item.iItem;

  if (index >= m_displayedLogs.size()) return 0;

  const LogMessageInfo& log = m_displayedLogs[index];

  if (item.mask & LVIF_TEXT) {
    static thread_local std::string
        utf8_buffer;  // ★ 改为 string 以接收 formatter 的输出
    static thread_local std::wstring wide_buffer;  // ★ 用于最终转换

    switch (static_cast<Column>(item.iSubItem)) {
      case Column::Icon:
        utf8_buffer = "";
          break;
      case Column::Timestamp:
        // 使用 m_timestampFormatter 来格式化时间戳
        utf8_buffer = m_timestampFormatter.format(log);
        break;
      case Column::Level:
        // 使用 m_levelFormatter 来获取级别字符串
        utf8_buffer = m_levelFormatter.format(log);
        break;
      case Column::ThreadID:
        // 对于简单类型，直接转换为 string
        {
          std::stringstream ss;
          ss << log.thread_id;
          utf8_buffer = ss.str();
        }
        break;
      case Column::Message:
        // 消息本身就是 UTF-8 string
        utf8_buffer = log.message;
        break;
    }

    // 将 UTF-8 字符串转换为 ListView 需要的宽字符 (wstring)
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8_buffer.c_str(), -1, NULL, 0);
    wide_buffer.resize(len);
    MultiByteToWideChar(CP_UTF8, 0, utf8_buffer.c_str(), -1, &wide_buffer[0],
                        len);

    item.pszText = &wide_buffer[0];
  }

  if (item.mask & LVIF_IMAGE) {
    if (static_cast<Column>(item.iSubItem) == Column::Icon) {
      item.iImage = GetIconIndexForLevel(log.level);
    }
  }

  return 0;
}

LRESULT CLogListControl::Impl::OnListViewColumnClick(NMLISTVIEW* pnmv) {
  Column clickedColumn = static_cast<Column>(pnmv->iSubItem);

  if (clickedColumn == m_sortState.column) {
    // 如果点击的是当前排序列，则切换排序方向
    m_sortState.ascending = !m_sortState.ascending;
  } else {
    // 否则，按新列升序排序
    m_sortState.column = clickedColumn;
    m_sortState.ascending = true;
  }

  // 更新列标题上的箭头指示
  HWND hHeader = ListView_GetHeader(m_hListView);
  HDITEM hdi = {HDI_FORMAT};
  for (int i = 0; i < static_cast<int>(Column::COUNT); ++i) {
    Header_GetItem(hHeader, i, &hdi);
    hdi.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
    if (i == static_cast<int>(m_sortState.column)) {
      hdi.fmt |= (m_sortState.ascending ? HDF_SORTUP : HDF_SORTDOWN);
    }
    Header_SetItem(hHeader, i, &hdi);
  }

  // 重新刷新显示
  RefreshDisplay();
  return 0;
}

LRESULT CLogListControl::Impl::OnListViewCustomDraw(NMLVCUSTOMDRAW* pcd) {
  switch (pcd->nmcd.dwDrawStage) {
    // 准备开始绘制
    case CDDS_PREPAINT:
      // 返回这个值，告诉系统我们想处理每个 item 的绘制
      return CDRF_NOTIFYITEMDRAW;

    // 准备绘制一个 item
    case CDDS_ITEMPREPAINT: {
      size_t index = pcd->nmcd.dwItemSpec;
      if (index < m_displayedLogs.size()) {
        const LogMessageInfo& log = m_displayedLogs[index];
        const auto& colors = s_themes.at(m_currentTheme);
        auto it = colors.logLevelColors.find(log.level);
        if (it != colors.logLevelColors.end()) {
          pcd->clrText = it->second;  // 设置文本颜色
        } else {
          pcd->clrText = colors.listTextDefault;
        }
        // pcd->clrTextBk = ...; // 也可以设置背景色
      }
    }
      // 返回这个值，告诉系统使用我们提供的颜色
      return CDRF_NEWFONT;
  }
  return CDRF_DODEFAULT;
}

void CLogListControl::Impl::CreateListView(HINSTANCE hInstance) {
  m_hListView = CreateWindowEx(
      WS_EX_CLIENTEDGE, WC_LISTVIEW, L"",
      WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_OWNERDATA | LVS_SHOWSELALWAYS, 0,
      0, 10, 10, m_hWnd, (HMENU)ControlId::ListView, hInstance, NULL);

  ListView_SetExtendedListViewStyle(m_hListView, LVS_EX_FULLROWSELECT |
                                                     LVS_EX_GRIDLINES |
                                                     LVS_EX_DOUBLEBUFFER);

  CreateImageList();
  ListView_SetImageList(m_hListView, m_hImageList, LVSIL_SMALL);

  SetupListViewColumns();
}

void CLogListControl::Impl::SetupListViewColumns() {
  LVCOLUMN lvc = {0};
  lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;

  struct ColInfo {
    const wchar_t* text;
    int width;
    int fmt;
  };
  ColInfo cols[] = {
      {L"", 24, LVCFMT_CENTER},       {L"Timestamp", 180, LVCFMT_CENTER},
      {L"Level", 80, LVCFMT_CENTER},  {L"Thread ID", 80, LVCFMT_CENTER},
      {L"Message", 800, LVCFMT_LEFT},
  };

  for (int i = 0; i < static_cast<int>(Column::COUNT); ++i) {
    lvc.iSubItem = i;
    lvc.pszText = (LPWSTR)cols[i].text;
    lvc.cx = cols[i].width;
    lvc.fmt = cols[i].fmt;
    ListView_InsertColumn(m_hListView, i, &lvc);
  }
}

void CLogListControl::Impl::CreateImageList() {
  m_hImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 6, 0);

  auto AddIcon = [&](LPCWSTR id) {
    HICON hIcon = (HICON)LoadImage(NULL, id, IMAGE_ICON, 16, 16, LR_SHARED);
    if (hIcon) ImageList_AddIcon(m_hImageList, hIcon);
  };

  AddIcon(IDI_INFORMATION);  // Info
  AddIcon(IDI_INFORMATION);  // Trace (复用)
  AddIcon(IDI_INFORMATION);  // Debug (复用)
  AddIcon(IDI_WARNING);      // Warn
  AddIcon(IDI_ERROR);        // Error
  AddIcon(IDI_ERROR);        // Critical (复用)
}

int CLogListControl::Impl::GetIconIndexForLevel(LogLevel level) const {
  switch (level) {
    case LogLevel::kInfo:
      return 0;
    case LogLevel::kTrace:
      return 1;
    case LogLevel::kDebug:
      return 2;
    case LogLevel::kWarn:
      return 3;
    case LogLevel::kError:
      return 4;
    case LogLevel::kCritical:
      return 5;
  }
  return 0;  // 默认
}
/**
 * @brief 处理子控件的颜色设置消息，以健壮的方式实现透明背景。
 *
 * 这是最终的推荐方案，它同时兼容启用了视觉样式和未启用视觉样式的场景。
 *
 * @param hWnd 父窗口句柄 (即 LogViewControl 的句柄)
 * @param uMsg 消息类型 (WM_CTLCOLORSTATIC 或 WM_CTLCOLORBTN)
 * @param wParam 子控件的设备上下文 (DC) 句柄
 * @param lParam 子控件的窗口句柄
 * @return HBRUSH 用于绘制背景的画刷句柄
 */
LRESULT CLogListControl::Impl::OnCtlColor(HWND /*hWnd*/, UINT uMsg,
                                          WPARAM wParam, LPARAM lParam) {
  HWND hwndChild = (HWND)lParam;
  int childId = GetDlgCtrlID(hwndChild);

  const auto& colors = s_themes.at(m_currentTheme);
  HDC hdc = (HDC)wParam;

  // 如果是状态栏背景板，或者状态栏上的静态文本，直接填充背景色
  if (childId == static_cast<int>(ControlId::StatusBar) ||
      hwndChild == m_hStatusTotal || hwndChild == m_hStatusDisplayed ||
      hwndChild == m_hStatusError || hwndChild == m_hStatusWarn ||
      hwndChild == m_hChkAutoScroll) {
    SetTextColor(hdc, colors.controlText);
    SetBkColor(hdc, colors.controlBg);
    return (LRESULT)colors.hControlBgBrush;
  }

  // 如果是复选框或其他需要透明背景的控件
  if (uMsg == WM_CTLCOLORBTN || uMsg == WM_CTLCOLORSTATIC) {
    // 尝试使用主题API绘制父窗口背景，实现透明效果
    HRESULT hr = DrawThemeParentBackground(hwndChild, hdc, NULL);
    if (SUCCEEDED(hr)) {
      // 背景已由主题引擎绘制，我们只需返回一个空画刷
      return (LRESULT)GetStockObject(NULL_BRUSH);
    }

    // 回退到经典方法
    SetTextColor(hdc, colors.controlText);
    SetBkMode(hdc, TRANSPARENT);
    // 这里返回父窗口的背景色画刷
    return (LRESULT)GetSysColorBrush(COLOR_WINDOW);  // 假设父窗口背景是这个
  }

  return DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}

// SRP: Gathers all filter settings from UI controls into a data structure.
FilterState CLogListControl::Impl::GatherFilterStateFromUI() const {
  FilterState filters;

  if (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckTrace)))
    filters.enabled_levels.insert(LogLevel::kTrace);
  if (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckDebug)))
    filters.enabled_levels.insert(LogLevel::kDebug);
  if (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckInfo)))
    filters.enabled_levels.insert(LogLevel::kInfo);
  if (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckWarn)))
    filters.enabled_levels.insert(LogLevel::kWarn);
  if (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckError)))
    filters.enabled_levels.insert(LogLevel::kError);
  if (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckCritical)))
    filters.enabled_levels.insert(LogLevel::kCritical);

  char search_buffer[256] = {0};
  GetWindowTextA(GetDlgItem(m_hWnd, static_cast<int>(ControlId::EditSearch)),
                 search_buffer, 256);
  filters.search_term = search_buffer;

  filters.use_regex =
      (IsDlgButtonChecked(m_hWnd, static_cast<int>(ControlId::CheckRegex)) ==
       BST_CHECKED);

  return filters;
}

// --- 辅助函数实现 ---

void CLogListControl::Impl::CreateChildControls(HINSTANCE hInstance) {
  // 使用 lambda 简化创建过程
  auto Create = [&](const wchar_t* className, const wchar_t* text, DWORD style,
                    ControlId id, int x, int y, int w, int h) {
    auto hWnd = CreateWindowW(className, text, WS_CHILD | WS_VISIBLE | style, x,
                              y, w, h, m_hWnd, (HMENU)id, hInstance, NULL);
    if (style & BS_AUTOCHECKBOX) m_logLevelCheckBoxes.push_back(hWnd);
    return hWnd;
  };

  // RichEdit
  Create(MSFTEDIT_CLASS, L"",
         WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_READONLY,
         ControlId::ListView, 0, 0, 0, 0);

  // Create(L"BUTTON", L"Filter by Level", BS_GROUPBOX, ControlId::GroupFilter,
  // 0,
  //        0, 0, 0);
  Create(L"BUTTON", L"Trace", BS_AUTOCHECKBOX, ControlId::CheckTrace, 0, 0, 0,
         0);
  Create(L"BUTTON", L"Debug", BS_AUTOCHECKBOX, ControlId::CheckDebug, 0, 0, 0,
         0);
  Create(L"BUTTON", L"Info", BS_AUTOCHECKBOX, ControlId::CheckInfo, 0, 0, 0, 0);
  Create(L"BUTTON", L"Warn", BS_AUTOCHECKBOX, ControlId::CheckWarn, 0, 0, 0, 0);
  Create(L"BUTTON", L"Error", BS_AUTOCHECKBOX, ControlId::CheckError, 0, 0, 0,
         0);
  Create(L"BUTTON", L"Critical", BS_AUTOCHECKBOX, ControlId::CheckCritical, 0,
         0, 0, 0);

  Create(L"STATIC", L"Search:", SS_CENTER | SS_CENTERIMAGE,
         ControlId::StaticSearch, 0, 0, 0, 0);
  Create(L"EDIT", L"", WS_BORDER | ES_AUTOHSCROLL, ControlId::EditSearch, 0, 0,
         0, 0);
  Create(L"BUTTON", L"Use Regex", BS_AUTOCHECKBOX, ControlId::CheckRegex, 0, 0,
         0, 0);

  Create(L"BUTTON", L"Clear", BS_PUSHBUTTON, ControlId::ButtonClear, 0, 0, 0,
         0);

  // Set default checks
  CheckDlgButton(m_hWnd, static_cast<int>(ControlId::CheckTrace), BST_CHECKED);
  CheckDlgButton(m_hWnd, static_cast<int>(ControlId::CheckDebug), BST_CHECKED);
  CheckDlgButton(m_hWnd, static_cast<int>(ControlId::CheckInfo), BST_CHECKED);
  CheckDlgButton(m_hWnd, static_cast<int>(ControlId::CheckWarn), BST_CHECKED);
  CheckDlgButton(m_hWnd, static_cast<int>(ControlId::CheckError), BST_CHECKED);
  CheckDlgButton(m_hWnd, static_cast<int>(ControlId::CheckCritical),
                 BST_CHECKED);
}

void CLogListControl::Impl::SetChildControlsFont() {
  NONCLIENTMETRICSW ncm = {sizeof(ncm)};
  if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)) {
    m_hFontUI = CreateFontIndirectW(&ncm.lfMessageFont);
  }
  if (m_hFontUI) {
    EnumChildWindows(
        m_hWnd,
        [](HWND hChild, LPARAM lParam) -> BOOL {
          SendMessage(hChild, WM_SETFONT, (WPARAM)lParam, TRUE);
          return TRUE;
        },
        (LPARAM)m_hFontUI);
    EnumChildWindows(
        m_hStatusBarWnd,
        [](HWND hChild, LPARAM lParam) -> BOOL {
          SendMessage(hChild, WM_SETFONT, (WPARAM)lParam, TRUE);
          return TRUE;
        },
        (LPARAM)m_hFontUI);
  }
}

void CLogListControl::Impl::LayoutChildControls(int width, int height) {
  // TODO: smart DPI
  // const float dpiScale = GetDpiForWindow(m_hWnd) / 96.0f;
  // const int PADDING = static_cast<int>(8 * dpiScale);

  if (width <= 0 || height <= 0) return;

  // --- 1. 定义布局常量 ---
  const int PADDING = 8;
  const int CONTROL_HEIGHT = 25;
  const int ROW_SPACING = 6;
  const int TOOLBAR_HEIGHT = (CONTROL_HEIGHT * 2) + (PADDING * 2) + ROW_SPACING;
  const int STATUS_BAR_HEIGHT = 24;  // 新增状态栏高度常量

  // --- 2. 布局顶部工具栏 (您的代码保持不变) ---
  // ... (布局第一行和第二行的代码)
  const int Y_ROW1 = PADDING;
  int current_x_r1 = PADDING;
  const int CHK_LEVEL_WIDTH = 60;
  auto LayoutCheckbox = [&](ControlId id) {
    MoveWindow(GetDlgItem(m_hWnd, static_cast<int>(id)), current_x_r1, Y_ROW1,
               CHK_LEVEL_WIDTH, CONTROL_HEIGHT, TRUE);
    current_x_r1 += CHK_LEVEL_WIDTH;
  };
  LayoutCheckbox(ControlId::CheckTrace);
  LayoutCheckbox(ControlId::CheckDebug);
  LayoutCheckbox(ControlId::CheckInfo);
  LayoutCheckbox(ControlId::CheckWarn);
  LayoutCheckbox(ControlId::CheckError);
  LayoutCheckbox(ControlId::CheckCritical);

  const int BTN_CLEAR_WIDTH = 90;
  int clear_btn_x = width - PADDING - BTN_CLEAR_WIDTH;
  MoveWindow(GetDlgItem(m_hWnd, static_cast<int>(ControlId::ButtonClear)),
             clear_btn_x, Y_ROW1, BTN_CLEAR_WIDTH, CONTROL_HEIGHT, TRUE);

  const int Y_ROW2 = Y_ROW1 + CONTROL_HEIGHT + ROW_SPACING;
  int current_x_r2 = PADDING;

  const int CHK_REGEX_WIDTH = 90;
  int regex_x = width - PADDING - CHK_REGEX_WIDTH;
  MoveWindow(GetDlgItem(m_hWnd, static_cast<int>(ControlId::CheckRegex)),
             regex_x, Y_ROW2, CHK_REGEX_WIDTH, CONTROL_HEIGHT, TRUE);

  const int LBL_SEARCH_WIDTH = 50;
  MoveWindow(GetDlgItem(m_hWnd, static_cast<int>(ControlId::StaticSearch)),
             current_x_r2, Y_ROW2, LBL_SEARCH_WIDTH, CONTROL_HEIGHT, TRUE);
  current_x_r2 += LBL_SEARCH_WIDTH;

  int search_edit_x = current_x_r2;
  int search_edit_width = regex_x - search_edit_x - PADDING;
  const int MIN_SEARCH_WIDTH = 100;
  if (search_edit_width < MIN_SEARCH_WIDTH) {
    search_edit_width = MIN_SEARCH_WIDTH;
  }
  MoveWindow(GetDlgItem(m_hWnd, static_cast<int>(ControlId::EditSearch)),
             search_edit_x, Y_ROW2, search_edit_width, CONTROL_HEIGHT, TRUE);

  // --- 3. 布局状态栏 (在 RichEdit 之前，以便计算其高度) ---
  int statusBarTop = height - STATUS_BAR_HEIGHT;
  MoveWindow(m_hStatusBarWnd, 0, height - STATUS_BAR_HEIGHT, width,
             STATUS_BAR_HEIGHT, TRUE);
  UpdateStatusBarLayout(width, STATUS_BAR_HEIGHT, statusBarTop);

  // --- 4. 布局富文本日志显示区 (填充剩余空间) ---
  int richEditY = TOOLBAR_HEIGHT;
  // 高度 = 总高度 - 工具栏高度 - 状态栏高度
  int richEditHeight = height - TOOLBAR_HEIGHT - STATUS_BAR_HEIGHT;

  // 安全检查，防止窗口过小时宽度/高度为负
  if (richEditHeight < 0) richEditHeight = 0;

  MoveWindow(m_hListView, PADDING, richEditY,
             width - (PADDING * 2),  // 宽度
             richEditHeight,         // 修正后的高度
             TRUE);
}

void CLogListControl::Impl::UpdateStatusBarLayout(int width, int height,
                                                  int topOffset) {
  const int kPadding = 8;
  const int kItemHeight = 20;
  // 计算控件在状态栏区域内的垂直居中位置
  const int kTopInStatus = (height - kItemHeight) / 2;
  // 计算控件相对于父窗口 m_hWnd 的最终 Y 坐标
  const int finalTop = topOffset + kTopInStatus;

  int x = kPadding;
  int widths[] = {90, 90, 70, 70};

  MoveWindow(m_hStatusTotal, x, kTopInStatus, widths[0], kItemHeight, TRUE);
  x += widths[0];
  MoveWindow(m_hStatusDisplayed, x, kTopInStatus, widths[1], kItemHeight, TRUE);
  x += widths[1];
  MoveWindow(m_hStatusError, x, kTopInStatus, widths[2], kItemHeight, TRUE);
  x += widths[2];
  MoveWindow(m_hStatusWarn, x, kTopInStatus, widths[3], kItemHeight, TRUE);

  const int kAutoScrollWidth = 80;
  MoveWindow(m_hChkAutoScroll, width - kAutoScrollWidth - kPadding, finalTop,
             kAutoScrollWidth, kItemHeight, TRUE);
}

void CLogListControl::Impl::UpdateStatusBarText() {
  wchar_t buffer[128];

  swprintf_s(buffer, L"总计: %zu", m_nTotalLogs);
  SetWindowTextW(m_hStatusTotal, buffer);

  swprintf_s(buffer, L"已显示: %zu", m_nDisplayedLogs);
  SetWindowTextW(m_hStatusDisplayed, buffer);

  size_t errors = m_logLevelCounts.count(LogLevel::kError)
                      ? m_logLevelCounts.at(LogLevel::kError)
                      : 0;
  swprintf_s(buffer, L"错误: %zu", errors);
  SetWindowTextW(m_hStatusError, buffer);

  size_t warnings = m_logLevelCounts.count(LogLevel::kWarn)
                        ? m_logLevelCounts.at(LogLevel::kWarn)
                        : 0;
  swprintf_s(buffer, L"警告: %zu", warnings);
  SetWindowTextW(m_hStatusWarn, buffer);
}

void CLogListControl::Impl::OnAutoScrollClicked() {
  LRESULT state = SendMessage(m_hChkAutoScroll, BM_GETCHECK, 0, 0);
  m_bAutoScroll = (state == BST_CHECKED);

  // 如果用户刚刚勾选了自动滚动，立即滚动到底部
  if (m_bAutoScroll) {
    SendMessage(m_hListView, WM_VSCROLL, SB_BOTTOM, 0);
  }
}

void CLogListControl::Impl::InitializeThemes() {
  if (s_themesInitialized) return;

  // --- Light theme ---
  ThemeColors lightTheme;
  lightTheme.listBg = GetSysColor(COLOR_WINDOW);
  lightTheme.listTextDefault = GetSysColor(COLOR_WINDOWTEXT);
  lightTheme.logLevelColors = {{LogLevel::kTrace, RGB(128, 128, 128)},
                               {LogLevel::kDebug, RGB(0, 128, 255)},
                               {LogLevel::kInfo, GetSysColor(COLOR_WINDOWTEXT)},
                               {LogLevel::kWarn, RGB(255, 165, 0)},
                               {LogLevel::kError, RGB(255, 0, 0)},
                               {LogLevel::kCritical, RGB(178, 34, 34)}};
  lightTheme.controlBg = GetSysColor(COLOR_BTNFACE);
  lightTheme.controlText = GetSysColor(COLOR_BTNTEXT);
  lightTheme.hControlBgBrush = CreateSolidBrush(lightTheme.controlBg);
  s_themes[Theme::Light] = lightTheme;

  // --- Dark theme ---
  ThemeColors darkTheme;
  darkTheme.listBg = RGB(30, 30, 30);
  darkTheme.listTextDefault = RGB(220, 220, 220);
  darkTheme.logLevelColors = {{LogLevel::kTrace, RGB(128, 128, 128)},
                              {LogLevel::kDebug, RGB(86, 156, 214)},
                              {LogLevel::kInfo, RGB(220, 220, 220)},
                              {LogLevel::kWarn, RGB(220, 200, 100)},
                              {LogLevel::kError, RGB(244, 100, 100)},
                              {LogLevel::kCritical, RGB(255, 80, 150)}};
  darkTheme.controlBg = RGB(51, 51, 51);
  darkTheme.controlText = RGB(220, 220, 220);
  darkTheme.hControlBgBrush = CreateSolidBrush(darkTheme.controlBg);
  s_themes[Theme::DarkVisualStudio] = darkTheme;

  s_themesInitialized = true;
}

// Impl内部的实现
void CLogListControl::Impl::SetTheme(Theme theme) {
  if (m_currentTheme == theme && m_hWnd)
    return;  // 如果主题未变，则不执行任何操作

  m_currentTheme = theme;
  ApplyCurrentTheme();
}

void CLogListControl::Impl::ApplyCurrentTheme() {
  if (!m_hWnd || s_themes.find(m_currentTheme) == s_themes.end()) {
    return;
  }

  const auto& colors = s_themes.at(m_currentTheme);

  // 1. 应用到 RichEdit
  SendMessage(m_hListView, EM_SETBKGNDCOLOR, 0, (LPARAM)colors.listBg);

  // 1. 应用到 RichEdit
  SendMessage(m_hListView, EM_SETBKGNDCOLOR, 0, (LPARAM)colors.listBg);

  // 2. 刷新日志内容以应用新的日志级别颜色 (RefreshDisplay 会处理)
  // RefreshDisplay(); //
  // 在这里调用会导致循环刷新，应在SetTheme的公共接口调用后手动刷新

  // 3. 强制重绘父窗口及其所有子控件以应用新颜色
  // 这将触发 WM_CTLCOLORSTATIC/BTN 等消息
  InvalidateRect(m_hWnd, NULL, TRUE);
  UpdateWindow(m_hWnd);  // 立即重绘
}

// 修改 GetColorForLogLevel 以使用主题
COLORREF CLogListControl::Impl::GetColorForLogLevel(LogLevel level) {
  const auto& colors = s_themes.at(m_currentTheme);
  auto it = colors.logLevelColors.find(level);
  if (it != colors.logLevelColors.end()) {
    return it->second;
  }
  return colors.listTextDefault;  // 返回默认颜色
}

}  // namespace Logging

#endif  //_WIN32